package uk.ac.aber.Blockmation;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;
import javax.swing.SwingUtilities;


/**
 * The main drawing area.
 * 
 * @author Aron
 */
public class DrawingPad extends Display 
		implements MouseMotionListener, MouseListener
{
    //restricting width/height, block size?
    final static Color COLOR = Color.black;
    private Point mousePos = new Point(0, 0);
    private boolean gridOn = false;
    private Color color;
	private Color mouseButtonsColor;
	private Color gridColor;

	public static final int POINT = 0;
    public static final int RECT = 1;
    public  static final int OVAL = 2;
    
    private int currentTool = 0;
	private Point mouseReleasedPt;
	private Point mousePressedPt;
    
    
    public DrawingPad()
    {
    	this(Color.white);
    }
    
    public DrawingPad(Color background)
    {
        super(background);
    	color = COLOR;
    	gridColor = color;
        this.addMouseMotionListener(this);
        this.addMouseListener(this);
    }

    public void paint(Graphics g)
    {
        super.paint(g);

        Graphics2D g2 = (Graphics2D) g;
        
        BufferedImage image = super.getDisplayedImage();
        Dimension block = super.getBlockSize();
        
        if (image != null)
        {
            g2.drawImage(image, null, 0, 0);
        }

        // check whether within image or outside on panel first
        int fullX = (int) Math.floor(mousePos.getX() / block.width);
        int fullY = (int) Math.floor(mousePos.getY() / block.height);

        g2.setColor(color);
        g2.fillRect(fullX * block.width, fullY * block.height, block.width,
            block.height);
        
        if (gridOn)
        {
	        for (int y=0; y < image.getHeight(); y+=block.height)
	        	for (int x=0; x < image.getWidth(); x+=block.width)
	        	{
	        		g2.setColor(gridColor); // sets the color of the grid
	        		g2.drawRect( x, y, block.width, block.height);
	        	}
        }
        g2.dispose();
        
    }

   
    //@Override
    public void mouseDragged(MouseEvent e)
    {
    	drawWithAppropriateTool(e);
    }

    //@Override
    public void mouseMoved(MouseEvent e)
    {
        mousePos = e.getPoint();
        repaint(); // repainting squared edge
    }

    //@Override
    public void mouseClicked(MouseEvent e)
    {
    }

    //@Override
    public void mouseEntered(MouseEvent e)
    {
    	//changing Cursor?
    }

    //@Override
    public void mouseExited(MouseEvent e)
    {
    	//changing Cursor?
    	mousePos = new Point(-1, -1);
    	repaint();
    }

    //@Override
    public void mousePressed(MouseEvent e)
    {
    	mousePressedPt = e.getPoint();
    	drawWithAppropriateTool(e);
    	
    }

    //@Override
    public void mouseReleased(MouseEvent e)
    {
    	mouseReleasedPt = e.getPoint();
    	
    	switch (currentTool)
    	{
    	case RECT: drawRectOnActualImgAtMousePts(mouseButtonsColor); break;
    	case OVAL: drawOvalOnActualImgAtMousePts(mouseButtonsColor); break;
    	}
    	
    }

    private void drawWithAppropriateTool(MouseEvent e)
    {
        if (SwingUtilities.isLeftMouseButton(e))
        {
        	mouseButtonsColor = color;
        }
        else
        {
        	mouseButtonsColor = super.getBackgroundColor();
        }
        
        switch (currentTool)
        {
        case POINT:	drawSquare(e.getPoint(), mouseButtonsColor); break;
        }
        
    }
    
    public Color getColor()
    {
        return color;
    }

    public void setColor(Color color)
    {
        this.color = color;
    }

    public void drawSquare(Point position, Color squareColor)
    {
        mousePos = position;
        
        BufferedImage image = super.getDisplayedImage();
        Dimension block = super.getBlockSize();

        // Note: the graphics context is the image not the panel context
        Graphics2D g2 = image.createGraphics();
        g2.setColor(squareColor);

        int fullX = (int) Math.floor(position.getX() / block.width);
        int fullY = (int) Math.floor(position.getY() / block.height);

        g2.fillRect(fullX * block.width, fullY * block.height, block.width,
            block.height);
        g2.dispose();

        repaint();
    }
    
    /*
     * to be included later? 
     * remember about Issue 2. BufferedImage pixel by pixel change!
     * 
     * public void setBackground(Color background) {
                    this.background = background;
            }
    */
    
    public void drawRectOnActualImgAtMousePts(Color rectColor)
    {
    	BufferedImage smallBim = super.getImage(); 
    	Graphics2D g2 = smallBim.createGraphics();
    	g2.setColor(rectColor);
    	int upX = (int)getActualIntPoint(mousePressedPt).getX();
    	int upY = (int)getActualIntPoint(mousePressedPt).getY();
    	int downX = (int)getActualIntPoint(mouseReleasedPt).getX();
    	int downY = (int)getActualIntPoint(mouseReleasedPt).getY();
    	System.out.format("upX %d, upY %d, downX %d, downY %d\n", upX, upY, downX, downY);
    	int width = downX - upX;
    	int height = downY - upY;
    	g2.drawRect(upX, upY, width, height);
    	g2.dispose();
    	super.setImage(smallBim);  
    }
    
    public void drawOvalOnActualImgAtMousePts(Color ovalColor)
    {
    	BufferedImage smallBim = super.getImage(); 
    	Graphics2D g2 = smallBim.createGraphics();
    	g2.setColor(ovalColor);
    	int upX = (int)getActualIntPoint(mousePressedPt).getX();
    	int upY = (int)getActualIntPoint(mousePressedPt).getY();
    	int downX = (int)getActualIntPoint(mouseReleasedPt).getX();
    	int downY = (int)getActualIntPoint(mouseReleasedPt).getY();
    	System.out.format("upX %d, upY %d, downX %d, downY %d\n", upX, upY, downX, downY);
    	int width = downX - upX;
    	int height = downY - upY;
    	g2.drawOval(upX, upY, width, height);
    	g2.dispose();
    	super.setImage(smallBim);  
    }
    
    public boolean showGrid(boolean showGrid)
    {
    	// only allow if block size is not too small  
        Dimension block = super.getBlockSize();
    	
    	if (block.width > 1 && block.width > 1)
    	{
        	if (showGrid) gridOn = true; else gridOn = false;
        	
        	repaint();
        	return true;
    	}
    		return false;// disallow if block size too small
    }
    
    public Point getActualIntPoint(Point zoomedPt)
    {
    	Dimension block = super.getBlockSize();
    	Point actualPt = new Point((int)zoomedPt.getX()/block.width, (int)zoomedPt.getY()/block.height);
    	
    	return actualPt;
    }

	public int getCurrentTool() {
		return currentTool;
	}

	public void setCurrentTool(int currentTool) {
		
		// set only if within available tools
		if (currentTool >= 0 && currentTool < 3)
		this.currentTool = currentTool;
	}

	public Color getGridColor() {
		return gridColor;
	}

	public void setGridColor(Color gridColor) {
		this.gridColor = gridColor;
	}

	public Point getMousePos() {
		return mousePos;
	}

	public Point getMousePressedPt() {
		return mousePressedPt;
	}

	public Point getMouseReleasedPt() {
		return mouseReleasedPt;
	}

	public boolean isGridOn() {
		return gridOn;
	}
	
	
}

